home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 22
/
Cream of the Crop 22.iso
/
os2
/
npswp182.zip
/
NPSWPSWA.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1995-10-22
|
18KB
|
492 lines
// Standard Window Animation DLL for NPS WPS Enhancer
// Copyright (C) 1995, N.P.S.
// 100 or more columns are necessary to read this file properly
#define INCL_PM
#include <os2.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include "npswpswa.h"
// to export
extern "C" BOOL EXPENTRY SpinFrame(AnimationData *padat);
extern "C" BOOL EXPENTRY VortexFrames(AnimationData *padat);
extern "C" BOOL EXPENTRY ScatterGatherFrames(AnimationData *padat);
extern "C" BOOL EXPENTRY SpikeFrames(AnimationData *padat);
extern "C" BOOL EXPENTRY FireworksFrames(AnimationData *padat);
const FIXED Fixed1 = 1 << 16;
static POINTL PointZero = { 0, 0 };
static MATRIXLF Matrix1 = { Fixed1, 0, 0, 0, Fixed1, 0, 0, 0, 1 }; // unit matrix
struct DisjointLine
{ POINTL ptStart, ptEnd;
};
LONG fixedMul(LONG lMultiplicand, FIXED fMultiplier);
FIXED fixedDiv(LONG lNumerator, LONG lDenominator);
POINTL operator*(const POINTL &point, const MATRIXLF &matrix);
MATRIXLF operator*(const MATRIXLF &matrix1, const MATRIXLF &matrix2);
MATRIXLF mix(const MATRIXLF &matrix1, const MATRIXLF &matrix2, FIXED fMix);
POINTL mix(const POINTL &point1, const POINTL &point2, FIXED fMix);
void drawDisjoint(HPS hps, DisjointLine *paDisjointLine, LONG cLines);
LONG setDisjointLine(DisjointLine *pDisjointLine, const POINTL& ptStart, const POINTL &ptEnd);
LONG setDisjointBox(DisjointLine *pDisjointLine,
const POINTL& ptCenter, const POINTL &ptRelRightTop);
inline POINTL operator+(POINTL &point1, POINTL &point2)
{ POINTL pointResult;
pointResult.x = point1.x + point2.x;
pointResult.y = point1.y + point2.y;
return pointResult;
}
inline POINTL operator-(POINTL &point1, POINTL &point2)
{ POINTL pointResult;
pointResult.x = point1.x - point2.x;
pointResult.y = point1.y - point2.y;
return pointResult;
}
inline MATRIXLF& operator*=(MATRIXLF &matrix1, const MATRIXLF &matrix2)
{ return matrix1 = matrix1 * matrix2;
}
BOOL EXPENTRY SpinFrame(AnimationData *padat)
{ if (padat->animCallType == AnimationDraw
|| padat->animCallType == AnimationErase)
{ POINTL aPtRectangle[4];
aPtRectangle[1].x = aPtRectangle[0].x = padat->ptRelRightTop.x;
aPtRectangle[1].y = -(aPtRectangle[0].y = padat->ptRelRightTop.y);
MATRIXLF matrix;
FIXED afxScale[2];
afxScale[0] = afxScale[1] = fixedDiv(padat->lStep, padat->cTotalSteps);
GpiScale(padat->hps, &matrix, TRANSFORM_REPLACE, afxScale, &PointZero);
GpiRotate(padat->hps, &matrix, TRANSFORM_ADD,
fixedDiv(padat->lParameter * (padat->lStep - padat->cTotalSteps),
padat->cTotalSteps),
&PointZero);
aPtRectangle[0] = aPtRectangle[0] * matrix;
aPtRectangle[1] = aPtRectangle[1] * matrix;
if ((aPtRectangle[0].x != 0 || aPtRectangle[0].y != 0)
&& (aPtRectangle[1].x != 0 || aPtRectangle[1].y != 0))
{ aPtRectangle[2] = padat->ptCenter + aPtRectangle[0];
aPtRectangle[3] = padat->ptCenter + aPtRectangle[1];
aPtRectangle[0] = padat->ptCenter - aPtRectangle[0];
aPtRectangle[1] = padat->ptCenter - aPtRectangle[1];
GpiMove(padat->hps, &aPtRectangle[3]);
GpiPolyLine(padat->hps, 4, aPtRectangle);
}
}
return TRUE;
}
BOOL EXPENTRY VortexFrames(AnimationData *padat)
{ switch (padat->animCallType)
{ case AnimationInitialize:
GpiRotate(padat->hps, (MATRIXLF *)padat->achBuffer, TRANSFORM_REPLACE,
72 * Fixed1, &padat->ptCenter);
break;
case AnimationDraw:
case AnimationErase:
{ POINTL ptBoxRel;
ptBoxRel.x = padat->ptRelRightTop.x * padat->lStep / padat->cTotalSteps;
ptBoxRel.y = padat->ptRelRightTop.y * padat->lStep / padat->cTotalSteps;
MATRIXLF matrix;
FIXED afxScale[2];
afxScale[0] = afxScale[1] = fixedDiv((padat->cTotalSteps - padat->lStep) * 5,
padat->cTotalSteps * 3);
GpiTranslate(padat->hps, &matrix, TRANSFORM_REPLACE, &padat->ptRelRightTop);
GpiScale(padat->hps, &matrix, TRANSFORM_ADD, afxScale, &padat->ptCenter);
GpiRotate(padat->hps, &matrix, TRANSFORM_ADD,
fixedDiv(padat->lParameter * padat->lStep, padat->cTotalSteps),
&padat->ptCenter);
DisjointLine adjline[5 * 4];
LONG cLines = 0;
POINTL ptBoxCenter = padat->ptCenter * matrix;
for (int iLoop = 0; iLoop < 5; iLoop++)
{ cLines += setDisjointBox(&adjline[cLines], ptBoxCenter, ptBoxRel);
ptBoxCenter = ptBoxCenter * *(MATRIXLF *)padat->achBuffer;
}
drawDisjoint(padat->hps, adjline, cLines);
break;
}
}
return TRUE;
}
BOOL EXPENTRY ScatterGatherFrames(AnimationData *padat)
{ if (padat->animCallType == AnimationDraw
|| padat->animCallType == AnimationErase)
{ LONG lDivisor = padat->lParameter;
POINTL ptBoxRel;
ptBoxRel.x = padat->ptRelRightTop.x * padat->lStep / (padat->cTotalSteps * lDivisor);
ptBoxRel.y = padat->ptRelRightTop.y * padat->lStep / (padat->cTotalSteps * lDivisor);
MATRIXLF matrix;
FIXED afxScale[2];
afxScale[0] = afxScale[1] = fixedDiv(padat->cTotalSteps * 3 - padat->lStep * 2,
padat->cTotalSteps);
GpiScale(padat->hps, &matrix, TRANSFORM_REPLACE, afxScale, &PointZero);
GpiTranslate(padat->hps, &matrix, TRANSFORM_ADD, &padat->ptCenter);
DisjointLine adjline[10 * 10 * 4]; // The maximum number of rects is 10 * 10
LONG cLines = 0;
for (int iRow = 0; iRow < lDivisor; iRow++)
{ for (int iColumn = 0; iColumn < padat->lParameter; iColumn++)
{ POINTL ptTileCenter;
ptTileCenter.x = (iRow * 2 - lDivisor + 1) * padat->ptRelRightTop.x / lDivisor;
ptTileCenter.y = (iColumn * 2 - lDivisor + 1) * padat->ptRelRightTop.y / lDivisor;
ptTileCenter = ptTileCenter * matrix;
cLines += setDisjointBox(&adjline[cLines], ptTileCenter, ptBoxRel);
}
}
drawDisjoint(padat->hps, adjline, cLines);
}
return TRUE;
}
BOOL EXPENTRY SpikeFrames(AnimationData *padat)
{ struct SpikeData
{ POINTL aPtTriangleEnd[16][3], aPtEndCenter[16], aPtTriangleCenter[16];
MATRIXLF aMatrixCircle[16];
};
switch (padat->animCallType)
{ case AnimationInitialize:
{ LONG xLeft = padat->rectWindow.xLeft,
xRight = padat->rectWindow.xRight,
yBottom = padat->rectWindow.yBottom,
yTop = padat->rectWindow.yTop;
POINTL *paPtTriangle = ((SpikeData *)padat->achBuffer)->aPtTriangleEnd[0],
*paPtCenter = ((SpikeData *)padat->achBuffer)->aPtEndCenter;
for (int iIndex = 0; iIndex < 16; iIndex++, paPtTriangle += 3, paPtCenter++)
{ paPtTriangle[0] = padat->ptCenter;
if (iIndex < 4)
{ paPtTriangle[1].y = paPtTriangle[2].y = yTop;
paPtTriangle[1].x = (xLeft * (4 - iIndex) + xRight * iIndex) / 4;
paPtTriangle[2].x = (xLeft * (3 - iIndex) + xRight * (iIndex + 1)) / 4;
}
else if (iIndex < 8)
{ paPtTriangle[1].x = paPtTriangle[2].x = xRight;
paPtTriangle[1].y = (yTop * (8 - iIndex) + yBottom * (iIndex - 4)) / 4;
paPtTriangle[2].y = (yTop * (7 - iIndex) + yBottom * (iIndex - 3)) / 4;
}
else if (iIndex < 12)
{ paPtTriangle[1].y = paPtTriangle[2].y = yBottom;
paPtTriangle[1].x = (xRight * (12 - iIndex) + xLeft * (iIndex - 8)) / 4;
paPtTriangle[2].x = (xRight * (11 - iIndex) + xLeft * (iIndex - 7)) / 4;
}
else
{ paPtTriangle[1].x = paPtTriangle[2].x = xLeft;
paPtTriangle[1].y = (yBottom * (16 - iIndex) + yTop * (iIndex - 12)) / 4;
paPtTriangle[2].y = (yBottom * (15 - iIndex) + yTop * (iIndex - 11)) / 4;
}
paPtCenter->x = (paPtTriangle[0].x + paPtTriangle[1].x + paPtTriangle[2].x) / 3;
paPtCenter->y = (paPtTriangle[0].y + paPtTriangle[1].y + paPtTriangle[2].y) / 3;
}
paPtCenter = ((SpikeData *)padat->achBuffer)->aPtTriangleCenter;
POINTL ptTriangleCenter;
ptTriangleCenter.x = padat->ptCenter.x;
ptTriangleCenter.y =
padat->ptCenter.y + (padat->ptRelRightTop.x + padat->ptRelRightTop.y) * 4 / 5;
for (iIndex = 0; iIndex < 16; iIndex++)
{ MATRIXLF matrix;
GpiRotate(padat->hps, &matrix, TRANSFORM_REPLACE,
(33 * Fixed1) + (-22 * Fixed1) * iIndex, &padat->ptCenter);
paPtCenter[iIndex] = ptTriangleCenter * matrix;
POINTL ptTemp =
paPtCenter[iIndex] - ((SpikeData *)padat->achBuffer)->aPtEndCenter[iIndex];
GpiTranslate(padat->hps, &((SpikeData *)padat->achBuffer)->aMatrixCircle[iIndex],
TRANSFORM_REPLACE, &ptTemp);
}
break;
}
case AnimationDraw:
case AnimationErase:
{ POINTL aPtTriangle[3];
DisjointLine adjline[16 * 3];
int cLines = 0;
FIXED fixedFactor;
MATRIXLF matrix;
FIXED afxScale[2];
afxScale[0] = afxScale[1] = fixedDiv(padat->lStep, padat->cTotalSteps);
if (padat->lStep < padat->cTotalSteps / 2)
{ fixedFactor = (Fixed1 - fixedDiv(padat->lStep * 2, padat->cTotalSteps))
* padat->lParameter;
for (int iIndex = 0; iIndex < 16; iIndex++)
{ GpiScale(padat->hps, &matrix, TRANSFORM_REPLACE, afxScale,
&((SpikeData *)padat->achBuffer)->aPtEndCenter[iIndex]);
GpiRotate(padat->hps, &matrix, TRANSFORM_ADD, fixedFactor,
&((SpikeData *)padat->achBuffer)->aPtEndCenter[iIndex]);
matrix *= ((SpikeData *)padat->achBuffer)->aMatrixCircle[iIndex];
for (int iAngle = 0; iAngle < 3; iAngle++)
{ aPtTriangle[iAngle] =
((SpikeData *)padat->achBuffer)->aPtTriangleEnd[iIndex][iAngle] * matrix;
}
for (iAngle = 0; iAngle < 3; iAngle++)
{ cLines += setDisjointLine(&adjline[cLines], aPtTriangle[iAngle],
aPtTriangle[(iAngle + 1) % 3]);
}
}
}
else
{ fixedFactor = fixedDiv(padat->lStep * 2 - padat->cTotalSteps, padat->cTotalSteps);
for (int iIndex = 0; iIndex < 16; iIndex++)
{ GpiScale(padat->hps, &matrix, TRANSFORM_REPLACE, afxScale,
&((SpikeData *)padat->achBuffer)->aPtEndCenter[iIndex]);
matrix *= mix(Matrix1, ((SpikeData *)padat->achBuffer)->aMatrixCircle[iIndex],
fixedFactor);
for (int iAngle = 0; iAngle < 3; iAngle++)
{ aPtTriangle[iAngle] =
((SpikeData *)padat->achBuffer)->aPtTriangleEnd[iIndex][iAngle] * matrix;
}
for (iAngle = 0; iAngle < 3; iAngle++)
{ cLines += setDisjointLine(&adjline[cLines], aPtTriangle[iAngle],
aPtTriangle[(iAngle + 1) % 3]);
}
}
}
drawDisjoint(padat->hps, adjline, cLines);
break;
}
}
return TRUE;
}
BOOL EXPENTRY FireworksFrames(AnimationData *padat)
{ const int NUMBER_OF_RECTS = 10;
struct FireworksData
{ POINTL aPtCenter[NUMBER_OF_RECTS];
};
switch (padat->animCallType)
{ case AnimationInitialize:
{ POINTL *paPtCenter = ((FireworksData *)padat->achBuffer)->aPtCenter;
POINTL ptRectCenter;
ptRectCenter.x = padat->ptCenter.x;
ptRectCenter.y =
padat->ptCenter.y + (padat->ptRelRightTop.x + padat->ptRelRightTop.y) * 5 / 3;
for (int iIndex = 0; iIndex < NUMBER_OF_RECTS; iIndex++)
{ MATRIXLF matrix;
GpiRotate(padat->hps, &matrix, TRANSFORM_REPLACE,
iIndex * (360 * Fixed1 / NUMBER_OF_RECTS), &padat->ptCenter);
paPtCenter[iIndex] = ptRectCenter * matrix;
}
break;
}
case AnimationDraw:
case AnimationErase:
{ POINTL ptTemp;
DisjointLine adjline[NUMBER_OF_RECTS * 4];
int cLines = 0;
FIXED fixedFactor = fixedDiv(padat->lStep, padat->cTotalSteps);
MATRIXLF matrix;
FIXED afxScale[2];
afxScale[0] = afxScale[1] = fixedFactor;
POINTL aPtRect[4], aPtTemp[4];
aPtRect[0].x = aPtRect[3].x = -padat->ptRelRightTop.x;
aPtRect[1].x = aPtRect[2].x = padat->ptRelRightTop.x;
aPtRect[0].y = aPtRect[1].y = padat->ptRelRightTop.y;
aPtRect[2].y = aPtRect[3].y = -padat->ptRelRightTop.y;
for (int iIndex = 0; iIndex < NUMBER_OF_RECTS; iIndex++)
{ GpiScale(padat->hps, &matrix, TRANSFORM_REPLACE, afxScale, &PointZero);
GpiRotate(padat->hps, &matrix, TRANSFORM_ADD,
(Fixed1 - fixedFactor) * padat->lParameter, &PointZero);
POINTL ptTemp;
ptTemp = mix(padat->ptCenter, ((FireworksData *)padat->achBuffer)->aPtCenter[iIndex],
fixedFactor);
GpiTranslate(padat->hps, &matrix, TRANSFORM_ADD, &ptTemp);
for (int iAngle = 0; iAngle < 4; iAngle++)
{ aPtTemp[iAngle] = aPtRect[iAngle] * matrix;
}
for (iAngle = 0; iAngle < 4; iAngle++)
{ cLines += setDisjointLine(&adjline[cLines], aPtTemp[iAngle],
aPtTemp[(iAngle + 1) % 4]);
}
}
drawDisjoint(padat->hps, adjline, cLines);
break;
}
}
return TRUE;
}
// drawing functions
void drawDisjoint(HPS hps, DisjointLine *paDisjointLine, LONG cLines)
{ // draw disjoint lines
// GpiPolyLineDisjoint is much faster than a few GpiLine's
if (cLines > 0) GpiPolyLineDisjoint(hps, cLines * 2, (PPOINTL)paDisjointLine);
}
LONG setDisjointLine(DisjointLine *pDisjointLine, const POINTL& ptStart, const POINTL &ptEnd)
{ // set the line data between ptStart and ptEnd
// return 1 if the line is valid, 0 if not
if (ptStart.x == ptEnd.x && ptStart.y == ptEnd.y) return 0;
else
{ pDisjointLine->ptStart = ptStart;
pDisjointLine->ptEnd = ptEnd;
return 1; // 1 struct was set
}
}
LONG setDisjointBox(DisjointLine *pDisjointLine,
const POINTL& ptCenter, const POINTL &ptRelRightTop)
{ // set the line data of the rectangle
// return the number of valid lines, 0 means there's no valid line
POINTL aPtRectangle[4];
for (int iIndex = 0; iIndex < 4; iIndex++)
{ aPtRectangle[iIndex].x =
ptCenter.x + (iIndex == 0 || iIndex == 3 ? -ptRelRightTop.x : ptRelRightTop.x);
aPtRectangle[iIndex].y = ptCenter.y + (iIndex <= 1 ? -ptRelRightTop.y : ptRelRightTop.y);
}
LONG cLines = 0;
for (iIndex = 0; iIndex < 4; iIndex++)
{ if (setDisjointLine(pDisjointLine, aPtRectangle[iIndex], aPtRectangle[(iIndex + 1) % 4]))
{ pDisjointLine++;
cLines++;
}
}
return cLines;
}
// helper functions for FIXED etc.
LONG fixedMul(LONG lMultiplicand, FIXED fxMultiplier)
{ // returns lMultiplicand * fxMultiplier as a LONG
// also returns a FIXED if lMultiplicand is a FIXED
return lMultiplicand * (fxMultiplier >> 16)
+ (lMultiplicand >> 16) * (fxMultiplier & 0xffff)
+ ((ULONG)((lMultiplicand & 0xffff) * (fxMultiplier & 0xffff)) >> 16);
}
FIXED fixedDiv(LONG lNumerator, LONG lDenominator)
{ // returns lNumerator / lDenominator as a FIXED
// also works well for 2 FIXED's
if (lNumerator == 0 || lDenominator == 0) return 0;
LONG lSignBit = (lNumerator ^ lDenominator) >> (sizeof(LONG) * 8 - 1);
lNumerator = abs(lNumerator);
lDenominator = abs(lDenominator);
int cShiftRemain = sizeof(SHORT) * 8;
while ((lDenominator & 1) == 0 && cShiftRemain > 0)
{ lDenominator >>= 1;
cShiftRemain--;
}
ULONG ulQuotient = 0, ulTemp;
do
{ while ((lNumerator & 0x80000000) == 0 && cShiftRemain > 0)
{ lNumerator <<= 1;
cShiftRemain--;
}
ulTemp = (ULONG)lNumerator / (ULONG)lDenominator;
lNumerator -= ulTemp * lDenominator;
ulQuotient += ulTemp << cShiftRemain;
} while (lNumerator != 0 && cShiftRemain > 0);
return (ulQuotient ^ lSignBit) - lSignBit; /* reverse sign if lSignBit = -1 */
}
POINTL operator*(const POINTL &point, const MATRIXLF &matrix)
{ // returns POINTL transformed by MATRIXLF
POINTL pointResult;
pointResult.x = fixedMul(point.x, matrix.fxM11) + fixedMul(point.y, matrix.fxM21) + matrix.lM31;
pointResult.y = fixedMul(point.x, matrix.fxM12) + fixedMul(point.y, matrix.fxM22) + matrix.lM32;
return pointResult;
}
POINTL mix(const POINTL &pointSource1, const POINTL &pointSource2, FIXED fMix)
{ // mix 2 POINTL's according to FIXED
POINTL pointResult;
pointResult.x = fixedMul(pointSource1.x, fMix) + fixedMul(pointSource2.x, Fixed1 - fMix);
pointResult.y = fixedMul(pointSource1.y, fMix) + fixedMul(pointSource2.y, Fixed1 - fMix);
return pointResult;
}
MATRIXLF operator*(const MATRIXLF &mtx1, const MATRIXLF &mtx2)
{ // returns product of 2 MATRIXLF's
MATRIXLF mtxProduct;
mtxProduct.fxM11 = fixedMul(mtx1.fxM11, mtx2.fxM11) + fixedMul(mtx1.fxM12, mtx2.fxM21);
mtxProduct.fxM12 = fixedMul(mtx1.fxM11, mtx2.fxM12) + fixedMul(mtx1.fxM12, mtx2.fxM22);
mtxProduct.lM13 = 0;
mtxProduct.fxM21 = fixedMul(mtx1.fxM21, mtx2.fxM11) + fixedMul(mtx1.fxM22, mtx2.fxM21);
mtxProduct.fxM22 = fixedMul(mtx1.fxM21, mtx2.fxM12) + fixedMul(mtx1.fxM22, mtx2.fxM22);
mtxProduct.lM23 = 0;
mtxProduct.lM31 = fixedMul(mtx1.lM31, mtx2.fxM11) + fixedMul(mtx1.lM32, mtx2.fxM21) + mtx2.lM31;
mtxProduct.lM32 = fixedMul(mtx1.lM31, mtx2.fxM12) + fixedMul(mtx1.lM32, mtx2.fxM22) + mtx2.lM32;
mtxProduct.lM33 = 1;
return mtxProduct;
}
MATRIXLF mix(const MATRIXLF &matrix1, const MATRIXLF &matrix2, FIXED fMix)
{ // mix 2 MATRIXLF's according to FIXED
MATRIXLF matrixResult;
for (int iIndex = 0; iIndex < 9; iIndex++)
{ ((PLONG)&matrixResult)[iIndex] =
fixedMul(((PLONG)&matrix1)[iIndex], fMix)
+ fixedMul(((PLONG)&matrix2)[iIndex], Fixed1 - fMix);
}
return matrixResult;
}